package rabbitas{
	import rabbitas.ns.Nodes;
	import rabbitas.attributes.AttributeName;

	/**
	 * @author martindyrby
	 */
	public class InstanceManager {
		private var instanceXML : XML;
		private var instanceCreator : InstanceCreator;
		private var eventManager : EventManager;
		private var host:RabbitAS;
		
		private var instances:Object;

		private var instanceDecorator:InstanceDecorator;

		public var propertyManager : PropertyManager;
		public var autoWireManager:AutoWireManager;
		public var liveCycleManager:LiveCycleManager;
		

		
		public function InstanceManager(conf:XML, hostapp:RabbitAS) {
			instanceXML = conf;
			host = hostapp;

			RabbitLogger.debug("InstanceManager created.");
		}
		
		public function init() :void {
			eventManager = new EventManager(host.ROOT.stage);
			
			instanceDecorator = new InstanceDecorator();
			instanceDecorator.instanceManager = this;
			
			instanceCreator = new InstanceCreator();
			instanceCreator.instanceManager = this;
			instanceCreator.instanceDecorator = instanceDecorator;
			instanceCreator.eventManager=eventManager;
			instanceCreator.autoWireManager=autoWireManager;
			
			instances = {};
		}

		public function resolveRootObject() : void {
			var def : XMLList = instanceXML.root;
			if (def.length() > 0) {
				instanceDecorator.decorateFromAttributes(def[0], host.ROOT);
				instanceDecorator.decorateFromChildren(def[0], host.ROOT);
			}
		}

		public function instantiateDiligentObjects() : Array {
			var instances:Array = new Array();
			for each (var diligentChild:XML in instanceXML.descendants(Nodes.objectQName).(hasOwnProperty("@" + AttributeName.LAZY_INIT) && @[AttributeName.LAZY_INIT] == "false")) {
				instances.push(getObjectById(diligentChild.@[AttributeName.ID]));
			}
			
			for each (var diligentStaticChild:XML in instanceXML.descendants(Nodes.staticQName).(hasOwnProperty("@" + AttributeName.LAZY_INIT) && @[AttributeName.LAZY_INIT] == "false")) {
				instances.push(getObjectById(diligentStaticChild.@[AttributeName.ID]));
			}
			return instances;
		}

		public function getObjectById(id:String):*{
			if(id.toLowerCase()=="root") return host.ROOT;
			if(id.toLowerCase()=="rabbit") return host;
			
			RabbitLogger.info("Creation of object with id", id, "requested");
			
			if(instances[id] != null) return instances[id];

			var def : XMLList = instanceXML.descendants(Nodes.objectQName).(hasOwnProperty("@" + AttributeName.ID) && @[AttributeName.ID] == id);
			if(def.length() == 0) {
				def = instanceXML.descendants(Nodes.staticQName).(hasOwnProperty("@" + AttributeName.ID) && @[AttributeName.ID] == id);
			}
			RabbitLogger.debug('def.length()', (def.length()));
			if(def.length() > 0) {
				var instance:* = instanceCreator.createFromXML(def[0]);
				instances[id]=instance;
				instanceCreator.decorate(def[0], instance);				
				liveCycleManager.initialize(instance, def[0]);
				return instance;
			}

			return propertyManager.resolvePropertyByName(id);
		}

		public function destroyObjectById(id:String) : * {
			RabbitLogger.info("Destruction of object with id", id, "requested");	
		}
	}
}
